package com.itkang.jmx;

import javax.management.*;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.lang.management.MemoryUsage;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 场景:
 * </p>
 *
 * @author york yuan
 * @version 1.0
 * @since 15/7/1下午3:50
 */
public class JmxManager {
    /**
     * 建立连接
     *
     * @param ip
     * @param jmxport
     * @return
     */
    public static MBeanServerConnection createMBeanServer(String ip,
                                                          String jmxport, String userName, String password) {
        try {
            String jmxURL = "service:jmx:rmi:///jndi/rmi://" + ip + ":"
                    + jmxport + "/jmxrmi";
            // jmx
            // url
            JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);

            Map map = new HashMap();
            String[] credentials = new String[]{userName, password};
            map.put("jmx.remote.credentials", credentials);
            JMXConnector connector = JMXConnectorFactory.connect(serviceURL,
                    map);
            MBeanServerConnection mbsc = connector.getMBeanServerConnection();
            return mbsc;

        } catch (Exception e) {
            // e.printStackTrace();
            System.err.println(ip + "的中间件不可以达");
        }
        return null;
    }


    /**
     * 获取所有属性
     *
     * @param mbeanServer
     * @param objName
     * @return
     */
    public static Map getAllAttribute(MBeanServerConnection mbeanServer,
                                      ObjectName objName) {
        if (mbeanServer == null || objName == null)
            throw new IllegalArgumentException();
        try {
            return null;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 使用MBeanServer获取对象名为[objName]的MBean的[objAttr]属性值
     * <p/>
     * 静态代码: return MBeanServer.getAttribute(ObjectName name, String attribute)
     *
     * @param mbeanServer - MBeanServer实例
     * @param objName     - MBean的对象名
     * @param objAttr     - MBean的某个属性名
     * @return 属性值
     */
    private static Object getAttribute(MBeanServerConnection mbeanServer,
                                       ObjectName objName, String objAttr) {
        if (mbeanServer == null || objName == null || objAttr == null)
            throw new IllegalArgumentException();
        try {
            return String.valueOf(mbeanServer.getAttribute(objName,
                    "currentThreadsBusy"));
        } catch (Exception e) {
            return null;
        }
    }


    public static void main(String[] args) {
        try {

            MBeanServerConnection  mbsc = createMBeanServer("172.19.3.54", "9000", "", "");

            //端口最好是动态取得
            ObjectName threadObjName = new ObjectName("Catalina:type=Connector,port=8080");
            MBeanInfo mbInfo = mbsc.getMBeanInfo(threadObjName);


            //------------------------- system ----------------------
            ObjectName runtimeObjName = new ObjectName("java.lang:type=Runtime");
            System.out.println("厂商:"+ (String)mbsc.getAttribute(runtimeObjName, "VmVendor"));
            System.out.println("程序:"+ (String)mbsc.getAttribute(runtimeObjName, "VmName"));
            System.out.println("版本:"+ (String)mbsc.getAttribute(runtimeObjName, "VmVersion"));
            Date starttime=new Date((Long)mbsc.getAttribute(runtimeObjName, "StartTime"));
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("启动时间:"+df.format(starttime));


            //堆使用率
            ObjectName heapObjName = new ObjectName("java.lang:type=Memory");
            MemoryUsage heapMemoryUsage =  MemoryUsage.from((CompositeDataSupport)mbsc.getAttribute(heapObjName, "HeapMemoryUsage"));
            long maxMemory = heapMemoryUsage.getMax();//堆最大
            long commitMemory = heapMemoryUsage.getCommitted();//堆当前分配
            long usedMemory = heapMemoryUsage.getUsed();
            System.out.println("heap:"+(double)usedMemory*100/commitMemory+"%");//堆使用率

            MemoryUsage nonheapMemoryUsage =  MemoryUsage.from((CompositeDataSupport)mbsc.getAttribute(heapObjName, "NonHeapMemoryUsage"));
            long noncommitMemory = nonheapMemoryUsage.getCommitted();
            long nonusedMemory = heapMemoryUsage.getUsed();
            System.out.println("nonheap:"+(double)nonusedMemory*100/noncommitMemory+"%");

//            ObjectName permObjName = new ObjectName("java.lang:type=MemoryPool,name=Perm Gen");
//            MemoryUsage permGenUsage =  MemoryUsage.from((CompositeDataSupport)mbsc.getAttribute(permObjName, "Usage"));
//            long committed = permGenUsage.getCommitted();//持久堆大小
//            long used = heapMemoryUsage.getUsed();//
//            System.out.println("perm gen:"+(double)used*100/committed+"%");//持久堆使用率

            //-------------------- Session ---------------
            ObjectName managerObjName = new ObjectName("Catalina:type=Manager,*");
            Set<ObjectName> s=mbsc.queryNames(managerObjName, null);
            for (ObjectName obj:s){
                System.out.println("应用名:"+obj.getCanonicalName().substring(obj.getCanonicalName().indexOf("/"),obj.getCanonicalName().indexOf(",")));
                ObjectName objname=new ObjectName(obj.getCanonicalName());
                System.out.println("最大会话数:"+ mbsc.getAttribute( objname, "maxActiveSessions"));
                System.out.println("会话数:"+ mbsc.getAttribute( objname, "activeSessions"));
                System.out.println("活动会话数:"+ mbsc.getAttribute( objname, "sessionCounter"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
